import {computed, nextTick, reactive, type Ref, ref, watch} from "vue";
import type {Meta, MetaView} from "../../../types/tool/meta.types";
import {Query} from "../../../tools/query";
import type {DTableProps} from "../../../types/table/m.table.types";
import type {DaoInfo, DataItem} from "../../../types/tool/dao.types.ts";
import {useDao} from "../../../tools/dao.ts";
import {$confirm, $message} from "../../../tools/feedback.ts";

export function useDTable(table: Ref, props: DTableProps) {
    const meta = computed<Meta>(() => ({db: props.db, entity: props.entity, code: props.code}))
    const info = reactive<DaoInfo>({current: 0, total: 0, size: props.size || 10, page: props.page || 1,})
    const query = computed<Query>(() => new Query({
        includes: {...props.excludes},
        excludes: {...props.excludes},
        size: info.size,
        page: info.page,
        orders: props.orders,
    }))

    const results = ref<DataItem[]>([])
    const view = ref<MetaView>({})
    const selection = computed<any[]>(() => table.value?.getSelection() || [])
    const {
        find_many,
        find_one,
        delete_many,
        save_one,
        delete_one,
        save_many,
        load_view,
        status,
        loading
    } = useDao(meta, {
        auth: props.auth,
        stop: () => nextTick().then(() => load())
    })

    watch(meta, () => {
        query.value.page = 1
        load_view((v) => {
            view.value = v
            load()
        })
    }, {deep: true, immediate: true})
    watch(query, () => load(), {immediate: true, deep: true})

    function load() {
        const ids = selection.value.map((e: any) => e.id)
        find_many(query.value as Query, (payload) => {
            const current = payload.results.length
            Object.assign(info, {current, total: payload.total})
            results.value = payload.results
            nextTick().then(() => {
                table.value?.setSelection(ids)
            })
        })
    }

    function remove(id?: number | string) {
        if (id) {
            delete_one(id, load)
        } else {
            const length = selection.value.length
            const content = selection.value.length ?
                `是否删除选中的${length}条数据？` :
                `是否删除当前所有的${info.total}条数据？`
            const id__in = selection.value.map(e => e.id)
            const q = length ? new Query({includes: {id__in}}) : undefined
            $confirm.warning(content, '删除确认')
                .then(() => delete_many(q || query.value as Query, () => load()))
                .catch(() => $message.info('取消删除'))
        }
    }

    function upload(array: any[]) {
        save_many(array)
    }

    function collect(callback: (item: DataItem) => void) {

        const length = selection.value.length
        if (length === 0) {
            save_one({saved: false}, callback)
        } else if (length === 1) {
            const id = selection.value[0].id
            find_one(id, callback)
        } else {
            callback(unify())
        }
    }

    function unify(): DataItem {
        const entries: any = []
        const keys = Object.keys(view.value.fields || {})
        keys.forEach((prop: string) => {
            const array = [...new Set([...selection.value.map(v => v[prop])])]
            if (array.length === 1) entries.push([prop, array[0]])
        })
        return Object.fromEntries(entries)
    }


    return {meta, query, view, info, results, selection, status, loading, load, remove, upload, collect}
}


